import {
  BarChart,
  EffectScatterChart,
  GaugeChart,
  LineChart,
  MapChart,
  PictorialBarChart,
  PieChart,
  RadarChart,
} from 'echarts/charts'
import {
  GridComponent,
  LegendComponent,
  TitleComponent,
  TooltipComponent,
} from 'echarts/components'
import { type ECharts, type EChartsCoreOption, init, registerTheme, throttle, use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import elementResizeDetectorMaker from 'element-resize-detector'
import { watch } from 'vue'

import { onBeforeUnmount, onMounted, ref, type WatchStopHandle } from 'vue'

import chalk from '~/config/chalk-chart-theme.json'

registerTheme('dark', chalk)

use([
  CanvasRenderer,
  PieChart,
  BarChart,
  LineChart,
  RadarChart,
  MapChart,
  GaugeChart,
  EffectScatterChart,
  PictorialBarChart,
  GridComponent,
  TitleComponent,
  TooltipComponent,
  LegendComponent,
])

export interface EChartsOption extends EChartsCoreOption {
}

const erd = elementResizeDetectorMaker()

export default function useEcharts(theme: string = 'dark', autoresize: boolean = true, debug: boolean = false) {
  const chartRef = ref<HTMLDivElement>()
  let chartInstance: ECharts | null = null

  function setOption(option: EChartsCoreOption) {
    chartInstance?.setOption(option)
  }

  const resizeObserver = new ResizeObserver(
    // 使用防抖（延迟 200ms 执行）
    throttle((entries: any) => {
      for (const entry of entries) {
        const { width, height } = entry.contentRect
        chartInstance?.resize({
          width,
          height,
          animation: {
            duration: 200,
            easing: 'linear',
          },
        })
      }
    }, 200),
  )

  const resize = throttle(() => {
    if (debug)
      console.log('resize')
    chartInstance?.resize({
      animation: {
        duration: 300,
        easing: 'linear',
      },
    })
  }, 60, true) as any

  let stopWatcher: WatchStopHandle | null = null

  function doResize(options: any = {
    animation: {
      duration: 600,
      easing: 'cubicInOut',
    },
  }) {
    chartInstance?.resize(options)
  }

  function hideLoading() {
    chartInstance?.hideLoading()
  }
  function showLoading() {
    chartInstance?.showLoading()
  }

  function addListener() {
    if (chartRef.value)
      resizeObserver.observe(chartRef.value)
  }

  function removeListener() {
    if (chartRef.value) {
      resizeObserver.unobserve(chartRef.value)
      resizeObserver.disconnect()
    }
  }

  onMounted(() => {
    if (chartRef.value) {
      chartInstance = init(chartRef.value, theme)
      if (autoresize) {
        addListener()
      }
    }
  })

  stopWatcher = watch(chartRef, () => {
    if (chartRef.value) {
      removeListener()
      chartInstance?.dispose()
      chartInstance = init(chartRef.value, theme)
      if (autoresize) {
        addListener()
      }
    }
  })

  onBeforeUnmount(() => {
    if (autoresize) {
      removeListener()
    }
    stopWatcher()
    chartInstance?.dispose()
    chartInstance = null
  })

  return { chartRef, setOption, resize, doResize, registerTheme, hideLoading, showLoading }
}
